package com.ourteam.system.service;

import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import com.ourteam.system.dao.IBaseSysDomainDAO;
import com.ourteam.system.dao.IBaseSysModuleDAO;
import com.ourteam.system.dao.IBaseSysRoleModuleRelateDAO;
import com.ourteam.system.dao.ISysDomainDAO;
import com.ourteam.system.dao.SysAction;
import com.ourteam.system.dao.SysActionDAOQueryBean;
import com.ourteam.system.dao.SysDomain;
import com.ourteam.system.dao.SysDomainDAOQueryBean;
import com.ourteam.system.dao.SysModule;
import com.ourteam.system.dao.SysModuleAccessLogDAOQueryBean;
import com.ourteam.system.dao.SysModuleDAOQueryBean;
import com.ourteam.system.dao.SysProperty;
import com.ourteam.system.dao.SysPropertyDAOQueryBean;
import com.ourteam.system.dao.SysResourceDAOQueryBean;
import com.ourteam.system.dao.SysRoleActionRelateDAOQueryBean;
import com.ourteam.system.dao.SysRoleModuleRelateDAOQueryBean;
import com.ourteam.system.domain.ApplicationDomain;
import com.ourteam.system.domain.SystemAction;
import com.ourteam.system.domain.SystemModule;
import com.ourteam.system.domain.SystemModuleAccessLogBean;
import com.ourteam.system.domain.SystemProperty;

public class SystemApplicationServiceImpl extends AbstractSystemApplicationService {

	@Override
	protected ApplicationDomain[] doGetApplicationDomains() throws Exception {
		SysDomainDAOQueryBean queryBean = new SysDomainDAOQueryBean();

		queryBean.createCriteria().andStatusEqualTo("IN_USE");

		queryBean.setSortProperty(IBaseSysDomainDAO.SortIndex);

		SysDomain[] sysDomains = sysDomainDao.query(queryBean);

		ApplicationDomain[] appDomains = new ApplicationDomain[sysDomains.length];

		for (int i = 0; i < sysDomains.length; i++) {
			SysDomain sysDomain = sysDomains[i];
			appDomains[i] = new ApplicationDomain(sysDomain);
		}

		return appDomains;
	}

	@Override
	protected int doQueryApplicationDomainCount(SysDomainDAOQueryBean aQueryBean) throws Exception {
		return sysDomainDao.queryCount(aQueryBean);
	}

	@Override
	protected ApplicationDomain[] doQueryApplicationDomains(SysDomainDAOQueryBean aQueryBean) throws Exception {

		SysDomain[] domains = sysDomainDao.query(aQueryBean);

		return ApplicationDomain.toArray(domains);
	}

	@Override
	protected void doCreateApplicationDomain(ApplicationDomain aApplicationDomain) throws Exception {

		SysDomain sysDomain = aApplicationDomain.convertToSysDomain();

		if (sysDomainDao.checkIsUnique(sysDomain) == false) {
			throw new Exception("Sys Domain[" + sysDomain.getDomainCode() + "] is alerady exist");
		}

		if (StringUtils.isBlank(sysDomain.getDomainTitelKey())) {
			sysDomain.setDomainTitelKey(sysDomain.getDomainName());
		}

		sysDomainDao.insert(sysDomain);

		if (sysDomain.getSortIndex() == null) {
			int maxSortIndex = queryApplicationDomainCount(null);
			sysDomain.setSortIndex(new Integer(maxSortIndex + 1));
			sysDomainDao.update(sysDomain);
		}

		// setSysDomainSortIndex(sysDomain.getId(),
		// sysDomain.getSortIndex().intValue());

	}

	@Override
	protected void doDeleteApplicationDomain(long aApplicationDomainId) throws Exception {

		SysResourceDAOQueryBean queryBean = new SysResourceDAOQueryBean();

		queryBean.createCriteria().andDomainIdEqualTo(Long.valueOf(aApplicationDomainId));

		if (sysResourceDao.queryCount(queryBean) > 0) {
			throw new Exception("Sys Domain[" + aApplicationDomainId + "] is refrenced by other resource");
		}

		SysModuleDAOQueryBean sysModuleDAOQueryBean = new SysModuleDAOQueryBean();

		sysModuleDAOQueryBean.createCriteria().andDomainIdEqualTo(aApplicationDomainId);

		SysModule[] sysModules = sysModuleDao.query(sysModuleDAOQueryBean);

		for (int i = 0; i < sysModules.length; i++) {
			deleteSystemModule(sysModules[i].getId());
		}

		sysDomainDao.delete(aApplicationDomainId);

		SysDomainDAOQueryBean sysDomainDAOQueryBean = new SysDomainDAOQueryBean();

		sysDomainDAOQueryBean.setSortProperty(ISysDomainDAO.SortIndex);

		SysDomain[] domains = sysDomainDao.query(sysDomainDAOQueryBean);

		for (int i = 0; i < domains.length; i++) {
			domains[i].setSortIndex(i + 1);
		}

		sysDomainDao.batchUpdate(domains);

	}

	@Override
	protected void doModifyApplicationDomain(ApplicationDomain aApplicationDomain) throws Exception {

		SysDomain sysDomain = aApplicationDomain.convertToSysDomain();

		if (sysDomainDao.checkIsUnique(sysDomain) == false) {
			throw new Exception("Sys Domain[" + sysDomain.getDomainCode() + "] is alerady exist");
		}

		sysDomainDao.update(sysDomain);

		if (sysDomain.getSortIndex() == null) {
			int maxSortIndex = getMaxApplicationDomainSort();
			sysDomain.setSortIndex(new Integer(maxSortIndex));
		}

		//setSysDomainSortIndex(sysDomain.getId(), sysDomain.getSortIndex().intValue());

	}

	@Override
	protected int doGetMaxApplicationDomainSort() throws Exception {
		SysDomainDAOQueryBean queryBean = new SysDomainDAOQueryBean();

		queryBean.addMaxFunctionProperty(IBaseSysDomainDAO.SortIndex, "maxSysDomainSort");

		Map[] results = sysDomainDao.querySelective(queryBean);

		return MapUtils.getIntValue(results[0], "maxSysDomainSort");

	}

	@Override
	protected void doSetSysDomainSortIndex(long aSysDomainId, int aSortIndex) throws Exception {
		if (aSortIndex < 0) {
			logger.warn("The Sort Index Must Gret Then 0");
			return;
		}

		SysDomain sysDomain = sysDomainDao.findById(aSysDomainId);

		if (sysDomain == null) {
			logger.warn("Can Not Found The System Domain[" + aSysDomainId + "]");
			return;
		}

		SysDomainDAOQueryBean queryBean = new SysDomainDAOQueryBean();
		
		queryBean.createCriteria().andIdNotEqualTo(aSysDomainId);

		queryBean.setSortProperty(IBaseSysDomainDAO.SortIndex);

		SysDomain[] sysDomains = sysDomainDao.query(queryBean);

		if (aSortIndex > 0) {
			sysDomains = (SysDomain[]) ArrayUtils.add(sysDomains, aSortIndex - 1, sysDomain);

		} else {
			sysDomains = (SysDomain[]) ArrayUtils.add(sysDomains, sysDomain);
		}

		for (int i = 0; i < sysDomains.length; i++) {
			sysDomains[i].setSortIndex(new Integer(i + 1));
		}

		sysDomainDao.batchUpdate(sysDomains);
	}

	@Override
	protected SystemModule[] doGetSystemModules(long domainId, long parentModuleId) throws Exception {
		SysModuleDAOQueryBean queryBean = new SysModuleDAOQueryBean();

		queryBean.createCriteria().andDomainIdEqualTo(domainId).andParentModuleIdEqualTo(parentModuleId);

		queryBean.setSortProperty(IBaseSysModuleDAO.SortIndex);

		return SystemModule.toArray(sysModuleDao.query(queryBean));
	}

	@Override
	protected SystemAction[] doGetSystemActions(long moduleId) throws Exception {

		SysActionDAOQueryBean queryBean = new SysActionDAOQueryBean();

		queryBean.createCriteria().andModuleIdEqualTo(moduleId);

		return SystemAction.toArray(sysActionDao.query(queryBean));
	}

	@Override
	protected ApplicationDomain doGetApplicationDomainById(long domainId) throws Exception {
		SysDomain sysDomain = sysDomainDao.findById(domainId);
		return sysDomain != null ? new ApplicationDomain(sysDomain) : null;
	}

	@Override
	protected SystemModule doGetSystemModuleById(long sysModuleId) throws Exception {
		SysModule sysModule = sysModuleDao.findById(sysModuleId);
		return sysModule != null ? new SystemModule(sysModule) : null;
	}

	@Override
	protected SystemAction doGetSystemActionById(long sysActionId) throws Exception {
		SysAction sysAction = sysActionDao.findById(sysActionId);
		return sysAction != null ? new SystemAction(sysAction) : null;
	}

	@Override
	protected void doCreateSystemModule(SystemModule systemModule) throws Exception {

		sysModuleDao.insert(systemModule.convertToSysModule());

		if (systemModule.getSortIndex() == 0) {
			int maxSortIndex = getMaxSystemModuleSort(systemModule.getDomainId(), systemModule.getParentModuleId());
			systemModule.setSortIndex(new Integer(maxSortIndex + 1));
		}

		setSysModuleSortIndex(systemModule.getId(), systemModule.getSortIndex());

	}

	@Override
	protected void doModifySystemModule(SystemModule systemModule) throws Exception {
		sysModuleDao.update(systemModule.convertToSysModule());

	}

	@Override
	protected void doDeleteSystemModule(long systemModuleId) throws Exception {

		SysActionDAOQueryBean sysActionDAOQueryBean = new SysActionDAOQueryBean();

		sysActionDAOQueryBean.createCriteria().andModuleIdEqualTo(systemModuleId);

		sysActionDao.delete(sysActionDAOQueryBean);

		sysActionDao.deleteSysRoleActionRelate(sysActionDAOQueryBean);

		SysModuleDAOQueryBean moduleDAOQueryBean = new SysModuleDAOQueryBean();

		moduleDAOQueryBean.createCriteria().andIdEqualTo(systemModuleId);

		sysModuleDao.deleteSysRoleModuleRelate(moduleDAOQueryBean);

		sysModuleDao.delete(systemModuleId);
	}

	@Override
	protected void doCreateSystemAction(SystemAction systemAction) throws Exception {

		SysModule sysModule = sysModuleDao.findById(systemAction.getModuleId());

		systemAction.setDomainId(sysModule.getDomainId());

		sysActionDao.insert(systemAction.convertToSysAction());

	}

	@Override
	protected void doModifySystemAction(SystemAction systemAction) throws Exception {
		sysActionDao.update(systemAction.convertToSysAction());
	}

	@Override
	protected void doDeleteSystemAction(long systemActionId) throws Exception {

		SysRoleActionRelateDAOQueryBean queryBean = new SysRoleActionRelateDAOQueryBean();

		queryBean.createCriteria().andActionIdEqualTo(systemActionId);

		sysRoleActionRelateDao.delete(queryBean);

		sysActionDao.delete(systemActionId);
	}

	@Override
	protected void doSetSysModuleSortIndex(long moduleId, int sortIndex) throws Exception {

		if (sortIndex < 0) {
			logger.warn("The Sort Index Must Gret Then 0");
			return;
		}

		SysModule sysModule = sysModuleDao.findById(moduleId);

		if (sysModule == null) {
			logger.warn("Can Not Found The System Module[" + moduleId + "]");
			return;
		}

		SysModuleDAOQueryBean queryBean = new SysModuleDAOQueryBean();

		queryBean.createCriteria().andDomainIdEqualTo(sysModule.getDomainId())
				.andParentModuleIdEqualTo(sysModule.getParentModuleId()).andIdNotEqualTo(moduleId);

		queryBean.setSortProperty(IBaseSysModuleDAO.SortIndex);

		SysModule[] sysModules = sysModuleDao.query(queryBean);

		if (sortIndex > sysModules.length + 1) {
			logger.warn("The Sort Index Must Less than " + sysModules.length + 1);
			return;
		}

		if (sortIndex > 0) {
			sysModules = (SysModule[]) ArrayUtils.add(sysModules, sortIndex - 1, sysModule);

		} else {
			sysModules = (SysModule[]) ArrayUtils.add(sysModules, sysModule);
		}

		for (int i = 0; i < sysModules.length; i++) {
			sysModules[i].setSortIndex(new Integer(i + 1));
		}

		sysModuleDao.batchUpdate(sysModules);

	}

	@Override
	protected int doGetMaxSystemModuleSort(long appDomainId, long parentModuleId) throws Exception {
		SysModuleDAOQueryBean queryBean = new SysModuleDAOQueryBean();

		queryBean.createCriteria().andDomainIdEqualTo(appDomainId).andParentModuleIdEqualTo(parentModuleId);

		queryBean.addMaxFunctionProperty(IBaseSysModuleDAO.SortIndex, "maxSysModuleSort");

		Map[] results = sysModuleDao.querySelective(queryBean);

		return MapUtils.getIntValue(results[0], "maxSysModuleSort");
	}

	@Override
	protected SystemModule doGetSystemModuleByCode(String moduleCode) throws Exception {

		SysModuleDAOQueryBean queryBean = new SysModuleDAOQueryBean();

		queryBean.createCriteria().andModuleCodeEqualTo(moduleCode);

		SysModule[] sysModules = sysModuleDao.query(queryBean);

		return ArrayUtils.isNotEmpty(sysModules) ? new SystemModule(sysModules[0]) : null;
	}

	@Override
	protected SystemModule[] doQuerySystemModules(SysModuleDAOQueryBean queryBean) throws Exception {

		if (queryBean == null) {
			queryBean = new SysModuleDAOQueryBean();
		}

		return SystemModule.toArray(this.sysModuleDao.query(queryBean));
	}

	@Override
	protected SystemModule[] doGetSysModulesByRoles(long domainId, long parentModuleId, long[] sysRoleIds)
			throws Exception {

		if (ArrayUtils.isEmpty(sysRoleIds)) {
			return new SystemModule[0];
		}

		SysRoleModuleRelateDAOQueryBean queryBean = new SysRoleModuleRelateDAOQueryBean();

		queryBean.setDistinct(true);

		queryBean.createCriteria().andDomainIdEqualTo(domainId).andParentModuleIdEqualTo(parentModuleId)
				.andRoleIdIn(sysRoleIds);

		queryBean.setSortProperty(IBaseSysRoleModuleRelateDAO.ModuleSortIndex);

		return SystemModule.toArray(this.sysRoleModuleRelateDao.querySysModule(queryBean));
	}

	@Override
	protected SystemProperty doGetSystemProperty(String catalog, String propertyCode) throws Exception {

		SysPropertyDAOQueryBean queryBean = new SysPropertyDAOQueryBean();

		queryBean.setDistinct(true);

		queryBean.createCriteria().andPropertyCatalogEqualTo(catalog).andPropertyCodeEqualTo(propertyCode);

		SysProperty[] properties = this.sysPropertyDao.query(queryBean);

		return ArrayUtils.isNotEmpty(properties) ? new SystemProperty(properties[0]) : null;
	}

	@Override
	protected SystemProperty[] doGetSystemPropertiesByCatalog(String catalog) throws Exception {

		SysPropertyDAOQueryBean queryBean = new SysPropertyDAOQueryBean();

		queryBean.createCriteria().andPropertyCatalogEqualTo(catalog);

		SysProperty[] properties = this.sysPropertyDao.query(queryBean);

		return SystemProperty.toArray(properties);
	}

	@Override
	protected void doModifySystemProperty(SystemProperty systemProperty) throws Exception {

		this.sysPropertyDao.update(systemProperty.convertToSysProperty());

	}

	@Override
	protected SystemAction doGetSystemActionByResourceCode(String recource) throws Exception {

		SysActionDAOQueryBean queryBean = new SysActionDAOQueryBean();

		queryBean.createCriteria().andActionResourceEqualTo(recource);

		SysAction[] sysActions = sysActionDao.query(queryBean);

		return ArrayUtils.isNotEmpty(sysActions) ? new SystemAction(sysActions[0]) : null;
	}

	@Override
	protected void doAddSystemModuleAccessLog(SystemModuleAccessLogBean systemModuleAccessBean) throws Exception {

		this.sysModuleAccessLogDao.insert(systemModuleAccessBean.convertToSysModuleAccessLog());

	}

	@Override
	protected SystemModuleAccessLogBean[] doQuerySystemModuleAccessLogs(SysModuleAccessLogDAOQueryBean queryBean)
			throws Exception {

		return SystemModuleAccessLogBean.toArray(this.sysModuleAccessLogDao.query(queryBean));
	}

	@Override
	protected int doQuerySystemModuleAccessLogCount(SysModuleAccessLogDAOQueryBean queryBean) throws Exception {

		return this.sysModuleAccessLogDao.queryCount(queryBean);
	}

	@Override
	protected SystemProperty doCreateNewSystemProperty(SystemProperty aSystemProperty) throws Exception {
		this.sysPropertyDao.insert(aSystemProperty.convertTo());
		return aSystemProperty;
	}

}
